package cn.tedu.reflection;

import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**本类用于测试暴力反射*/
public class TestReflect2 {
    /**测试1:通过暴力反射技术获取并且操作私有属性*/
    @Test
    public void getFie2() throws Exception {
        //获取字节码对象
        Class<?> clazz = Person.class;
        //获取指定的私有属性，注意要传入指定的参数名，而且要抛出异常
        Field field = clazz.getDeclaredField("name");
        //直接打印刚刚获取到的属性对象
        System.out.println(field);
        //通过刚刚获取到的私有属性对象,查看他的类型
        System.out.println(field.getType());//获取类型
        System.out.println(field.getType().getName());//获取类型名
        /**设置属性*/
        //给刚刚获取到的字段对象，设置属性
        //需要指定到底是给哪个对象的name属性设置值，没有对象创建对象
        Object obj = clazz.newInstance();
        //暴力反射，需要设置私有可见的权限
        field.setAccessible(true);

        //利用反射给刚刚获取到的字段对象设置属性值
        //field就是我们刚刚获取到的name属性
        //set(m,n)--m是给哪个对象的name 属性设置值，n是具体设置的值是什么
        field.set(obj,"海棉宝宝");
        //打印查看刚刚设置的属性值
        //field.get(m)--fild表示的就是name属性，m代表刚刚给哪个对象设置值
        System.out.println(field.get(obj));
    }
    /**测试1.2:通过暴力反射技术给私有属性age设置值为18*/
    @Test
    public void getFie3() throws Exception{
        Class<?> clazz = Person.class;
        Field field = clazz.getDeclaredField("age");
//        System.out.println(field);
        field.setAccessible(true);
        Object o1 = clazz.newInstance();
        field.set(o1,18);
        System.out.println(field.get(o1));

    }
    /**测试2.通过暴力反射技术获取并执行私有方法*/
    @Test
    public void getFunction2() throws Exception {
        Class<Person> clazz = Person.class;
        //通过字节码对象获取对应的私有方法对象method,代表的就是save(int,String)这个方法
        Method method = clazz.getDeclaredMethod("save", int.class, String.class);
        //暴力反射需要设置私有可见的权限
        method.setAccessible(true);
        //没有对象需要先通过反射技术创建对象
        Object p1 = clazz.newInstance();
        /**invoke(o,x,y,z...),表示通过反射技术给对应的对象执行指定的方法
         * o:值得就是对应的对象
         * x,y,z...:执行对应方法时需要传入的参数*/
        //通过方法对象调用invoke()执行私有方法
        //给p1对象执行save(666,""),method就是上面获取到的save方法
        method.invoke(p1,666,"哈哈哈");
    }
    @Test
    public void getFunction3() throws Exception {
        Class<?> clazz = Person.class;
        Method method = clazz.getDeclaredMethod("update");
        method.setAccessible(true);
        Object p2 = clazz.newInstance();
        method.invoke(p2);
    }
}

